import {
  ActionType,
  ModalForm,
  PageContainer,
  ProDescriptions,
  ProDescriptionsItemProps,
  ProFormDatePicker,
  ProFormDateTimePicker,
  ProFormInstance,
  ProFormSelect,
  ProFormText,
  ProFormTreeSelect,
  ProTable,
} from '@ant-design/pro-components';
import { Button, Drawer, FormInstance, Popconfirm, Result, Tag, message, theme } from 'antd';
import React, {
  ReactNode,
  forwardRef,
  useCallback,
  useEffect,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';
import { checkRespSuccessful } from '@/utils/serviceUtils';
import { Access, useAccess } from '@umijs/max';
import { ShowModalTypeEnum } from '@/constants';
import { getAllKeysTree } from '@/utils/treeUtils';

export type SearchTablePageRefType = {
  refresh: () => void;
  setSearchFieldValue: (name: string, value: any) => void;
  searchSubmit: () => void;
  setModalFormFieldValue: (name: string, value: any) => void;
};

const SearchTablePage = <RowType extends PageType.DefaultRowType>(
  {
    tableName,
    getRowById,
    updateRow,
    addRow,
    deleteRowById,
    deleteRowsByIdList,
    getRowsByPage,
    getAll,
    exportData,
    modalFormItems,
    columns,
    pageSize = 10,
    actionRender,
    toolBarRender,
    rowSelection,
    pagination,
    permissionKey = {},
    onAdd,
    onAdded,
    onUpdate,
    onUpdated,
    onDeleted,
    leftSide,
    params,
    onReset,
    onModalFormOpen,
    showExpandableAllBtn,
    rowProps,
    grid,
    modalFormWidth = 600,
    modalFormLabelCol = { flex: '8em' },
  }: PageType.SearchTablePageProps<RowType>,
  ref?: React.ForwardedRef<SearchTablePageRefType>,
) => {
  // 权限控制
  const access = useAccess();
  // 新建窗口的弹窗
  const [modalOpen, setModalOpen] = useState<boolean>(false);
  // 分布更新窗口的弹窗
  const [actionType, setActionType] = useState<ShowModalTypeEnum>(ShowModalTypeEnum.CREATE);
  // 展示详情的窗口
  const [showDetail, setShowDetail] = useState<boolean>(false);
  // 选中的当前行
  const [currentRow, setCurrentRow] = useState<RowType>();
  // 选中的多行
  const [selectedItemIdList, setSelectedItemIdList] = useState<React.Key[]>([]);
  const [expandedRowKeys, setExpandedRowKeys] = useState<React.Key[]>([]);
  const [allKeys, setAllKeys] = useState<React.Key[]>([]);
  const [isExpandedAll, setIsExpandedAll] = useState<boolean>(false);

  useEffect(() => {
    setExpandedRowKeys(isExpandedAll ? allKeys : []);
  }, [isExpandedAll]);

  const tableActionRef = useRef<ActionType>();
  const searchFormRef = useRef<FormInstance>();
  const modalFormRef = useRef<ProFormInstance<RowType>>();
  const { useToken } = theme;
  const { token } = useToken();
  const [messageApi, contextHolder] = message.useMessage();

  const [tableColumns, setTableColumns] = useState<PageType.CloumnType<RowType>[]>();
  const [modalNode, setModalNode] = useState<ReactNode>();

  useImperativeHandle(
    ref,
    () => ({
      refresh: () => {
        tableActionRef.current?.reload();
      },
      setSearchFieldValue: (name, value) => {
        searchFormRef.current?.setFieldValue(name, value);
      },
      searchSubmit: () => {
        searchFormRef.current?.submit();
      },
      setModalFormFieldValue: (name, value) => {
        modalFormRef.current?.setFieldValue(name, value);
      },
    }),
    [tableActionRef, searchFormRef, modalFormRef],
  );

  const handleAddOrUpdate = useCallback(async (item: RowType, flag: ShowModalTypeEnum) => {
    const tipText = flag === ShowModalTypeEnum.UPDATE ? '更新' : '添加';
    const hide = message.loading(`正在${tipText}${tableName}信息`);

    try {
      let res: API.Resp = { success: false, message: `暂不支持${tipText}${tableName}` };
      if (flag === ShowModalTypeEnum.UPDATE && updateRow) {
        res = await updateRow(item);
      } else if (flag === ShowModalTypeEnum.CREATE && addRow) {
        res = await addRow(item);
      }

      hide();
      if (checkRespSuccessful(res)) {
        message.success(`${tipText}成功`);
        return true;
      } else {
        message.error(`${tipText}失败，后台响应：${res.message}，请重试`);
        return false;
      }
    } catch (error) {
      hide();
      message.error(`${tipText}失败，请重试`);
      return false;
    }
  }, []);

  useEffect(() => {
    const column = [
      ...columns.map((item) => {
        let tempItem = item;
        if (item.showDetail) {
          tempItem = {
            ...tempItem,
            render: (dom: ReactNode, entity: RowType) => {
              return (
                <a
                  onClick={() => {
                    setCurrentRow(entity);
                    setShowDetail(true);
                  }}
                >
                  {dom || '-'}
                </a>
              );
            },
          };
        }
        if (item.valueType === 'tag') {
          tempItem = {
            ...tempItem,
            valueType: 'select',
            render: (text: string, record: any) => {
              let color = 'default';
              let reanderText = text;
              try {
                const value = record[item.dataIndex];
                color = item.valueEnum[value].tagColor || 'default';
                reanderText = item.valueEnum[value].text;
              } catch (err) {
                console.error(err);
              }
              return <Tag color={color}>{reanderText}</Tag>;
            },
          };
        }
        return {
          ...tempItem,
        };
      }),
    ];
    if (updateRow || deleteRowById) {
      column.push({
        title: '操作',
        key: 'control',
        hideInSearch: true,
        valueType: 'option',
        render: (text: string, record: RowType) => {
          const nodes: ReactNode[] = [
            updateRow && (
              <Access
                key="update"
                accessible={
                  permissionKey && permissionKey.update
                    ? access.permissionFilter(permissionKey.update)
                    : true
                }
              >
                <a
                  key="edit"
                  onClick={() => {
                    if (onUpdate && record.id !== undefined) {
                      onUpdate(record.id);
                    }
                    setActionType(ShowModalTypeEnum.UPDATE);
                    setCurrentRow(record);
                    setModalOpen(true);
                    if (onModalFormOpen) {
                      onModalFormOpen();
                    }
                  }}
                  type="link"
                >
                  编辑
                </a>
              </Access>
            ),
            deleteRowById && (
              <Access
                key="delete"
                accessible={
                  permissionKey && permissionKey.delete
                    ? access.permissionFilter(permissionKey.delete)
                    : true
                }
              >
                <Popconfirm
                  key="delete"
                  placement="topRight"
                  title={`删除当前${tableName}`}
                  description={`是否确认删除当前${tableName}，删除后将不可恢复`}
                  onConfirm={() => {
                    if (record.id === undefined) {
                      messageApi.error(`系统异常，原因为：选中删除的${tableName} ID 为空`);
                      return;
                    }
                    deleteRowById(record.id)
                      .then((res) => {
                        if (!checkRespSuccessful(res)) {
                          messageApi.error(`删除${tableName}失败，后台响应：${res.message}`);
                          return;
                        }
                        if (onDeleted && record.id !== undefined) {
                          onDeleted([record.id]);
                        }
                        messageApi.success(`删除${tableName}成功`);
                        setShowDetail(false);
                        tableActionRef.current?.reload();
                      })
                      .catch((err) => {
                        messageApi.error(`删除${tableName}失败，后端系统异常`);
                        console.error(err);
                      });
                  }}
                >
                  <a
                    type="link"
                    style={{
                      color: token.colorErrorText,
                    }}
                  >
                    删除
                  </a>
                </Popconfirm>
              </Access>
            ),
          ];
          if (actionRender) {
            return actionRender(text, record, nodes);
          }
          return nodes;
        },
      });
    }
    setTableColumns(column);
    setModalNode(
      <>
        {columns.map((item) => {
          switch (item.valueType) {
            case 'select':
            case 'tag':
              return (
                <ProFormSelect
                  key={item.key || (item.dataIndex as string)}
                  hidden={item.hideInModal}
                  name={item.dataIndex}
                  label={item.title as string}
                  options={item.options}
                  valueEnum={item.valueEnum}
                  rules={item.rules}
                  tooltip={item.modalFormTooltip}
                  request={item.request}
                  colProps={item.colProps}
                  style={item.style}
                  labelCol={item.labelCol}
                />
              );
            case 'treeSelect':
              return (
                <ProFormTreeSelect
                  allowClear={item.allowClear}
                  secondary={item.secondary}
                  key={item.key || (item.dataIndex as string)}
                  hidden={item.hideInModal}
                  name={item.dataIndex}
                  label={item.title as string}
                  valueEnum={item.valueEnum}
                  rules={item.rules}
                  tooltip={item.modalFormTooltip}
                  request={item.request}
                  fieldProps={item.fieldProps}
                  colProps={item.colProps}
                  style={item.style}
                  labelCol={item.labelCol}
                />
              );
            case 'date':
              return (
                <ProFormDatePicker
                  allowClear={item.allowClear}
                  secondary={item.secondary}
                  key={item.key || (item.dataIndex as string)}
                  hidden={item.hideInModal}
                  name={item.dataIndex}
                  label={item.title as string}
                  rules={item.rules}
                  tooltip={item.modalFormTooltip}
                  fieldProps={item.fieldProps}
                  colProps={item.colProps}
                  style={item.style}
                  labelCol={item.labelCol}
                />
              );
            case 'dateTime':
              return (
                <ProFormDateTimePicker
                  allowClear={item.allowClear}
                  secondary={item.secondary}
                  key={item.key || (item.dataIndex as string)}
                  hidden={item.hideInModal}
                  name={item.dataIndex}
                  label={item.title as string}
                  rules={item.rules}
                  tooltip={item.modalFormTooltip}
                  fieldProps={item.fieldProps}
                  colProps={item.colProps}
                  style={item.style}
                  labelCol={item.labelCol}
                />
              );
            default:
              return (
                <ProFormText
                  key={item.key || (item.dataIndex as string)}
                  hidden={item.hideInModal}
                  name={item.dataIndex}
                  label={item.title as string}
                  tooltip={item.modalFormTooltip}
                  rules={item.rules}
                  colProps={item.colProps}
                  style={item.style}
                  labelCol={item.labelCol}
                />
              );
          }
        })}
      </>,
    );
  }, [
    columns,
    messageApi,
    tableActionRef,
    setCurrentRow,
    setShowDetail,
    setActionType,
    setModalOpen,
  ]);

  return (
    <>
      {contextHolder}
      <PageContainer
        ghost
        header={{
          title: '',
          breadcrumb: {},
        }}
      >
        <Access
          key="list"
          accessible={
            permissionKey && permissionKey.list ? access.permissionFilter(permissionKey.list) : true
          }
          fallback={
            <Result status="403" title="无权限" subTitle={`暂无${tableName}查看权限`}></Result>
          }
        >
          <div
            style={{
              width: '100%',
              display: 'flex',
            }}
          >
            {leftSide}
            <div
              style={{
                flex: '1 1 auto',
                marginLeft: leftSide && token.margin,
              }}
            >
              <ProTable<RowType>
                headerTitle={`${tableName}列表`}
                columns={tableColumns}
                actionRef={tableActionRef}
                formRef={searchFormRef}
                cardBordered
                columnEmptyText=""
                expandable={
                  showExpandableAllBtn && getAll
                    ? {
                        expandedRowKeys: expandedRowKeys,
                        onExpandedRowsChange: (keys) => {
                          setExpandedRowKeys([...keys]);
                        },
                        defaultExpandAllRows: isExpandedAll,
                      }
                    : undefined
                }
                onReset={() => {
                  if (onReset) {
                    onReset();
                  }
                  tableActionRef.current?.reload();
                }}
                params={params}
                request={async (params) => {
                  const { current, ...validateParam } = params;
                  let errMsg;
                  if (getAll) {
                    const res = await getAll({
                      ...validateParam,
                      pageNum: String(current) || '1',
                    });
                    if (checkRespSuccessful(res)) {
                      if (showExpandableAllBtn && res.data) {
                        setAllKeys(getAllKeysTree(res.data, { key: 'id' }));
                      }
                      return res;
                    }
                    errMsg = res.message;
                  } else if (getRowsByPage) {
                    const res = await getRowsByPage({
                      ...validateParam,
                      pageNum: String(current) || '1',
                    });
                    if (checkRespSuccessful(res)) {
                      return {
                        data: res.data?.list,
                        total: res.data?.total,
                        success: true,
                      };
                    }
                    errMsg = res.message;
                  }

                  messageApi.error(`${tableName}列表数据获取失败，后台响应：${errMsg}`);
                  return {
                    success: false,
                  };
                }}
                rowSelection={
                  rowSelection === false
                    ? false
                    : {
                        type: rowSelection || 'checkbox',
                        onChange: (selectedRowKeys: React.Key[]) => {
                          setSelectedItemIdList(selectedRowKeys);
                        },
                      }
                }
                rowKey="id"
                search={{
                  labelWidth: 'auto',
                }}
                options={{
                  setting: {
                    listsHeight: 400,
                  },
                }}
                pagination={
                  pagination === false
                    ? false
                    : pagination || {
                        pageSize,
                        showQuickJumper: true,
                      }
                }
                dateFormatter="string"
                toolBarRender={() => {
                  let nodes = [
                    showExpandableAllBtn && (
                      <Button
                        onClick={() => {
                          setIsExpandedAll(!isExpandedAll);
                        }}
                        type="primary"
                      >
                        {isExpandedAll ? '折叠所有' : '展开所有'}
                      </Button>
                    ),
                    deleteRowsByIdList && (
                      <Access
                        key="multipleDelete"
                        accessible={
                          permissionKey && permissionKey.multipleDelete
                            ? access.permissionFilter(permissionKey.multipleDelete)
                            : true
                        }
                      >
                        <Popconfirm
                          title={`批量删除选中的${tableName}`}
                          description={`是否确认删除选中的${tableName}，删除后将不可恢复`}
                          disabled={selectedItemIdList.length <= 0}
                          onConfirm={() => {
                            if (selectedItemIdList.length <= 0) {
                              messageApi.error(
                                `批量删除${tableName}失败，原因为未选中任何${tableName}`,
                              );
                              return;
                            }
                            deleteRowsByIdList(selectedItemIdList)
                              .then((res) => {
                                if (checkRespSuccessful(res)) {
                                  messageApi.error(
                                    `批量删除${tableName}失败，后台响应：${res.message}`,
                                  );
                                  return;
                                }
                                messageApi.success(`批量删除${tableName}成功`);
                                if (onDeleted) {
                                  onDeleted([...selectedItemIdList]);
                                }
                                tableActionRef.current?.reload();
                                if (tableActionRef.current?.clearSelected) {
                                  tableActionRef.current.clearSelected();
                                }
                              })
                              .catch((err) => {
                                messageApi.error(`批量删除${tableName}失败，后端系统异常`);
                                console.error(err);
                              });
                          }}
                        >
                          <Button disabled={selectedItemIdList.length <= 0}>批量删除</Button>
                        </Popconfirm>
                      </Access>
                    ),
                    exportData && (
                      <Access
                        key="export"
                        accessible={
                          permissionKey && permissionKey.export
                            ? access.permissionFilter(permissionKey.export)
                            : true
                        }
                      >
                        <Button
                          onClick={() => {
                            messageApi.info('暂不支持该功能');
                          }}
                          type="primary"
                        >
                          导出
                        </Button>
                      </Access>
                    ),
                    addRow && (
                      <Access
                        key="add"
                        accessible={
                          permissionKey && permissionKey.add
                            ? access.permissionFilter(permissionKey.add)
                            : true
                        }
                      >
                        <Button
                          onClick={() => {
                            if (onAdd) {
                              onAdd();
                            }
                            setActionType(ShowModalTypeEnum.CREATE);
                            setCurrentRow(undefined);
                            setModalOpen(true);
                            if (onModalFormOpen) {
                              onModalFormOpen();
                            }
                          }}
                          type="primary"
                        >
                          新建
                        </Button>
                      </Access>
                    ),
                  ];
                  if (toolBarRender) {
                    nodes = toolBarRender(nodes);
                  }
                  return nodes;
                }}
              />
            </div>
          </div>
        </Access>
      </PageContainer>
      {modalOpen && (
        <ModalForm
          title={`${actionType === ShowModalTypeEnum.CREATE ? '新建' : '编辑'}${tableName}`}
          width={modalFormWidth}
          formRef={modalFormRef}
          layout="horizontal"
          rowProps={rowProps}
          grid={grid}
          labelCol={modalFormLabelCol}
          open={modalOpen}
          omitNil
          modalProps={{
            maskClosable: false,
          }}
          isKeyPressSubmit
          request={async () => {
            if (getRowById && actionType === ShowModalTypeEnum.UPDATE && currentRow?.id) {
              const res = await getRowById(currentRow?.id);
              if (checkRespSuccessful(res)) {
                return res.data;
              } else {
                return null;
              }
            }
            return { ...currentRow };
          }}
          onOpenChange={setModalOpen}
          onFinish={async (values) => {
            if (!values) {
              return;
            }
            if (actionType === ShowModalTypeEnum.CREATE) {
              delete values.id;
            }
            const success = await handleAddOrUpdate(values as RowType, actionType);
            if (!success) {
              return;
            }
            setModalOpen(false);
            setShowDetail(false);
            setCurrentRow(undefined);
            tableActionRef.current?.reload();
            if (actionType === ShowModalTypeEnum.CREATE) {
              if (onAdded) {
                onAdded();
              }
            } else {
              if (onUpdated && values.id !== undefined) {
                onUpdated(values.id);
              }
            }
          }}
        >
          {modalFormItems || modalNode}
        </ModalForm>
      )}
      <Drawer
        width={600}
        open={showDetail}
        onClose={() => {
          setCurrentRow(undefined);
          setShowDetail(false);
        }}
        closable={false}
      >
        {currentRow && (
          <ProDescriptions<RowType>
            column={1}
            title={currentRow?.name || '详情'}
            request={async () => {
              if (getRowById && typeof currentRow.id !== 'undefined') {
                return getRowById(currentRow.id);
              }
              return { data: { ...currentRow } };
            }}
            columns={tableColumns as ProDescriptionsItemProps<RowType>[]}
          />
        )}
      </Drawer>
    </>
  );
};

export default forwardRef(SearchTablePage) as <RowType extends PageType.DefaultRowType>(
  props: PageType.SearchTablePageProps<RowType> & {
    ref?: React.ForwardedRef<SearchTablePageRefType>;
  },
) => JSX.Element;
